﻿/**
 * grpc服务端测试用例
 * @author ZhroRui
 */

#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>

#include <string>
#include <vector>

#include "hello.grpc.pb.h"

/**
 * 作为grpc服务,继承hello.proto定义的接口,实现服务端的业务逻辑
 */
class HelloImpl final : public myGrpc::Hello::Service {
 public:
  /**
   * 本接口函数用于客户端-服务端应答模式的测试
   * @param context
   * @param request 客户端的消息
   * @param response 响应进行返回的消息
   * @return 当前的执行状态
   */
  grpc::Status Echo(grpc::ServerContext *context,
                    const myGrpc::EchoRequest *request,
                    myGrpc::EchoRequest *response) override {
    // 接收来自客户端的消息
    const auto &receiveVal{request->message()};
    // 处理请求
    std::cout << "Received message: " << receiveVal << std::endl;

    // 写入返回的消息
    response->set_message("Hello: " + receiveVal);
    // 反正状态
    return grpc::Status::OK;
  }

  /**
   * 本接口函数用于客户端1次请求,服务端流式返回数据的测试
   * @param context
   * @param request 客户端的消息
   * @param writer 服务端流式写入的handle
   * @return 当前的执行状态
   */
  grpc::Status ServerStream(
      grpc::ServerContext *context, const myGrpc::EchoRequest *request,
      grpc::ServerWriter<myGrpc::EchoRequest> *writer) override {
    // 接收来自客户端的消息
    const auto &receiveVal{request->message()};
    // 准备返回的数据
    myGrpc::EchoRequest reply{};
    // 流式写入
    for (int i = 0; i < 10; ++i) {
      // 更新消息
      reply.set_message(receiveVal + " " + std::to_string(i));
      // 写入
      writer->Write(reply);
    }

    // 返回状态,此时会触发客户端的end,结束流传输
    return grpc::Status::OK;
  }

  grpc::Status ClientStream(grpc::ServerContext *context,
                            grpc::ServerReader<myGrpc::EchoRequest> *reader,
                            myGrpc::EchoRequest *response) override {
    // 准备接收消息的实例
    myGrpc::EchoRequest request{};

    // 逐个读取客户端发送的请求
    while (reader->Read(&request)) {
      // 处理请求
      std::cout << "Received message: " << request.message() << std::endl;
    }
    // 生成响应，可以根据请求内容生成不同的响应
    response->set_message("Echo: " + request.message());

    // 返回状态,此时会触发客户端的end,结束流传输
    return grpc::Status::OK;
  }

  grpc::Status DuplexStream(
      grpc::ServerContext *context,
      grpc::ServerReaderWriter<myGrpc::EchoRequest, myGrpc::EchoRequest>
          *stream) override {
    // 准备接收消息的实例
    myGrpc::EchoRequest request{};

    // 循环处理来自客户端的请求
    while (stream->Read(&request)) {
      // 处理请求
      std::cout << "Received message: " << request.message() << std::endl;

      // 准备响应的数据
      myGrpc::EchoRequest response{};
      response.set_message("Echo: " + request.message());

      // 向客户端发送响应
      stream->Write(response);
    }

    // 返回状态,此时会触发客户端的end,结束流传输
    return grpc::Status::OK;
  }
};

void runServer() {
  // 初始化grpc监听的ip:port
  std::string serverAddr{"localhost:8080"};

  // 启动健康检查服务
  grpc::EnableDefaultHealthCheckService(true);
  grpc::reflection::InitProtoReflectionServerBuilderPlugin();
  // 设置监听ip/port
  grpc::ServerBuilder builder{};
  builder.AddListeningPort(serverAddr, grpc::InsecureServerCredentials());
  // 注册服务
  HelloImpl service{};
  builder.RegisterService(&service);

  const auto server{builder.BuildAndStart()};
  std::cout << "server listening on: " << serverAddr << std::endl;
  server->Wait();
}

int main(int argc, char *argv[]) {
  runServer();
}
